﻿//----------------------------------------------------------------
// Desc: 引擎杂项功能API
// Edit: ShowLong, http://blog.csdn.net/showlong
//
// Date Created: 2010-06-11
//
// Update Date : 
//
// Copyright (c) Fuel4D (http://www.fuel4d.com), All rights reserved.
//
//   本页所有函数可多线程访问
//----------------------------------------------------------------
#pragma once


//----------------------------------------------------------------
// 
//----------------------------------------------------------------
// 判断 Fuel4D 引擎使用的字符集是否是unicode
extern FAPI bool FIsUnicode();
// 获取程序的工作目录（与EXE文件在同一目录，尾部带有'\\'）
extern FAPI const WCHAR* const FGetRootPathW();
extern FAPI const ACHAR* const FGetRootPathA();
// 获取程序的执行文件全路径
extern FAPI const WCHAR* const FGetExePathW();
extern FAPI const ACHAR* const FGetExePathA();
// 获取EXE的文件名，不带扩展名
extern FAPI const WCHAR* const FGetExeFilenameW();
extern FAPI const ACHAR* const FGetExeFilenameA();
// 在调试控制台打印一条信息，加入文件行号，尾部自动加入换行（支持各平台和控制台）
#if !(FUEL_OS_ANDROID)
extern FAPI void FCDECL FOutDebugStrW(const WCHAR* file, const size_t line, const WCHAR* fmt, ...);
#endif
extern FAPI void FCDECL FOutDebugStrA(const ACHAR* file, const size_t line, const ACHAR* fmt, ...);
// 在调试控制台打印一条信息，不作任何更改，直接打印（支持各平台和控制台，需自行添加\n在串尾）
extern FAPI void FOutDebugStringW(const WCHAR* str);
extern FAPI void FOutDebugStringA(const ACHAR* str);
// 在调试控制台输出指定内存块
// .p 内存首地址
// .size 需要打印多长的内存数据，单位：字节
// .hex_mode 是否16进制，否则10进制
// .line_nums 打印的时候每行显示多少个
extern FAPI void FOutDebugMemory(void* p, size_t size, bool hex_mode = true, size_t line_nums = 32);
// 统一的取得时间函数（单位毫秒）
extern FAPI DWORD FGetTime();
// 测试CPU性能标记
#if FUEL_OS_WINDOWS
extern FAPI void FCPUID(DWORD type_id, DWORD ret_vl[4]);
#endif


//----------------------------------------------------------------
// math
//----------------------------------------------------------------
// 比较最大值（是返回值为正确结果，入参不改）
template < typename _Ty >
FINLINE _Ty FMax(_Ty a, _Ty b){ return (a) > (b) ? (a) : (b); }
// 比较最小值（是返回值为正确结果，入参不改）
template < typename _Ty >
FINLINE _Ty FMin(_Ty a, _Ty b){ return (a) < (b) ? (a) : (b); }
// 夹住一个值（是返回值为正确结果，入参不改）
template < typename _Ty >
FINLINE _Ty FClamp(_Ty vl, _Ty vmin, _Ty vmax){ if (vl < vmin) vl = vmin; if (vl > vmax) vl = vmax; return vl; }
// 快速开方，需要CPU支持SSE指令
FINLINE float FSqrt(float x);
// 快速同时开方4个float
FINLINE void FSqrt4(float (&in_x)[4], float (&out_x)[4]);
// 快速平方根倒数: 1/sqrtf(x)
FINLINE float FInvSqrt(float x);
// 快速平方根倒数4个float
FINLINE void FInvSqrt4(float (&in_x)[4], float (&out_x)[4]);
// 测试该值是不是2的幂
FINLINE bool FIsPower(int x);
// 将某值扩展为2的幂
FINLINE int FToPower(int x);
// 取符点数的整数部分，即向下取整， FGetInteger(f + 1.0f) 即为向上取整
FINLINE int FGetInteger(float x);
// 取符点数的余数部分
FINLINE float FGetFractional(float x);
// 将符点数以0.5为中线，向上或向下取整
FINLINE int FGetRound(float x);
// 取符点数绝对值
FINLINE float FAbsF(float x);
// 整数取绝对值
FINLINE int FAbsI(int x);
// 测试两个数的符号是否相同
template < typename _Ty >
FINLINE bool FTestSymbol(_Ty a, _Ty b);
// 取CPU周期时间
#if _MSC_VER > 1200
FINLINE UINT64 FGetCPUCycleTime();
#endif
// 取图片尺寸的除数因子
FINLINE float FGetTextureSizeGene(UINT size);
// 快速生成字符串HASH
// .make_lower 先转为小写再生成HASH
extern FAPI FIDHASH FGetHashA(const ACHAR* szstr, bool make_lower = false);
extern FAPI FIDHASH FGetHashW(const WCHAR* szstr, bool make_lower = false);
extern FAPI FIDHASH64 FGetHash64A(const ACHAR* szstr, bool make_lower = false);
extern FAPI FIDHASH64 FGetHash64W(const WCHAR* szstr, bool make_lower = false);
// 创建唯一数据ID, 主键和索引已知情况下 // 注意条件：主健在[0-255]闭区间，索引在[0-4194303]闭区间
extern FAPI FDATA_ID FCreateDataID(FDATA_KEY key, FDATA_INDEX index);
// 生成唯一数据ID, 主健已知，索引随机
extern FAPI FDATA_ID FGenerateDataID(FDATA_KEY key);
// 从唯一数据ID中获取主健
extern FAPI FDATA_KEY FGetKeyFromDataID(FDATA_ID& id);
// 从唯一数据ID中获取索引
extern FAPI FDATA_INDEX FGetIndexFromDataID(FDATA_ID& id);
// 修改唯一数据ID的主健
extern FAPI FDATA_ID& FSetKeyToDataID(FDATA_ID& id, FDATA_KEY key);
// 修改唯一数据ID的索引
extern FAPI FDATA_ID& FSetIndexToDataID(FDATA_ID& id, FDATA_INDEX index);
// 整数随机（闭区间）
extern FAPI int FRandI(int imin, int imax);
// 符点数随机（闭区间）
extern FAPI float FRandF(float fmin, float fmax);
// 已经矩形的边长，随机求矩形边线上面的点
extern FAPI void FRandPointByRect(float w, float h, float& x, float& y);
// 已知椭圆的两个轴长（半径），随机求椭圆边线上的点（圆也可以用此函数）
// 如果任意一个轴长小于0则失败，否则不会失败
extern FAPI bool FRandPointByEllipse(float a, float b, float& x, float& y);
// 通过1-100之间的概率判断能否满足
FINLINE bool FProbability(int vl);
// 角度转弧度，如：180度=(3.14159/2)弧度
FINLINE float FToRadian(float degree);
// 弧度转角度，如：3.14159弧度=360度
FINLINE float FToDegree(float radian);
// 线性插值
// .t 取值范转为[0.0f,1.0f]闭区间
template < typename _Ty >
FINLINE _Ty FSlerp(_Ty a, _Ty b, float t);
// 测试两个圆是否相交，2D，无论是否相交都将返回两个圆的距离
// .r0, v0 圆A的半径和坐标
// .r1, v1 圆B的半径和坐标
// .dist 返回两个圆的距离，不需要则填0
// .return 返回是否碰撞
struct FVECTOR2;
extern FAPI bool FCircleIntersect(float r0, FVECTOR2* v0, float r1, FVECTOR2* v1, float* dist = 0);
// 测试两个球是否相交，3D，无论是否相交都将返回两个圆的距离
// .r0, v0 圆A的半径和坐标
// .r1, v1 圆B的半径和坐标
// .dist 返回两个圆的距离，不需要则填0
// .return 返回是否碰撞
struct FVECTOR3;
extern FAPI bool FSphereIntersect(float r0, FVECTOR3* v0, float r1, FVECTOR3* v1, float* dist = 0);
// 生成验证字符串，由数字，字母组组成
// .out 输出地址（如果为空会生成失败）
// .char_count 输出字符数量（如果小于等于0会生成失败）
// .valid_char 随机生成的有效字符表。如果为空则使用默认机制：除去数字0、大写字母O、小写字母o 这三个以外的其它
// .valid_count 字符表数量，如：_T("1234578ABCDEFGHJKLMPQRSTUVWXYacefghijkmnrstuvwxy")，其中数字不含069，等等类推
extern FAPI bool FGenVerifyString(ACHAR* out, size_t char_count, const ACHAR* valid_char, size_t valid_count);
// 拼合区域
// .width, height 目标区域尺寸
// .area_list 传入区域列表，返回拼合完成的结果
struct IFUniteArea
{
    DWORD_PTR user_data, user_ex;   // 两个用户数据（用户参数）
    float sx, sy;                   // 存放计算结果（不填）
    float sw, sh;                   // 必须指定该矩型区域尺寸（必填参数）
    IFUniteArea(){ user_data = user_ex = 0; sw = sh = 0; }
};
typedef FVector< IFUniteArea > FV_UNITE_AREA;
extern FAPI bool FUniteArea(float width, float height, FV_UNITE_AREA& area_list);
// 弧度转为单字节
FINLINE BYTE FRadianToByte(float rad);
// 字节转为弧度
FINLINE float FByteToRadian(BYTE by);
// 通过平面的三个点生成法线
// .v0,v1,v2 平面上的三个点
// .normal 输出法线
extern FAPI void FMakeNormal(FVECTOR3& v0, FVECTOR3& v1, FVECTOR3& v2, FVECTOR3& normal);
// 设置地块的高度（FWD用的）
extern FAPI void FSetChunkHeight(BYTE* dst, float vl);
// 获取地块的高度（FWD用的）
extern FAPI float FGetChunkHeight(BYTE* dst);
// 设置地块的法线（FWD用的）
extern FAPI void FSetChunkNormal(BYTE* dst, float angle_x, float angle_y);
// 设置地块混合度（FWD用的）
extern FAPI void FSetChunkAlpha(BYTE* dst, BYTE layer, float alpha);
// 获取地块混合度（FWD用的）
extern FAPI float FGetChunkAlpha(BYTE* dst, BYTE layer);
// 通过坐标点的高程计算各轴角度（FWD用的）
extern FAPI void FGetTerrainAngle(float z0, float z1, float z2, float z3, float zc, float& angle_y, float& angle_x);
// ken perlin 噪声生成
extern FAPI float FPerlinNoise1D(float x);
extern FAPI float FPerlinNoise2D(float x, float y);
extern FAPI float FPerlinNoise3D(float x, float y, float z);
// 创建噪声贴图内存数据
// .frequency 强度(0,1)开区间
extern FAPI void FPerlinNoiseTexture(UINT width, UINT height, float frequency, FV_FLOAT& out);
// 取得流的宽度
extern FAPI DWORD FGetStreamSride(EF_STREAM_TYPE st);
// 原子加法
extern FAPI LONG FInterlockedIncrement(LONG FVOLATILE *lpAddend);
// 原子减法
extern FAPI LONG FInterlockedDecrement(LONG FVOLATILE *lpAddend);


//----------------------------------------------------------------
// memory
//----------------------------------------------------------------
// 安全内存复制
// .dst, src 目标和源
// .count 字节数
// .return 返回dst
FINLINE void* FMemcpy(void* dst, const void* src, size_t count);
// 安全内存清零
// .dst 目标
// .count 字节数
// .return 返回dst
FINLINE void* FMemzero(void* dst, size_t count);
// 安全比较
// .left, right 两段内存
// .count 字节数
// .return 相同返回0
FINLINE int FMemcmp(const void* left, const void* right, size_t count);
// 通过KEY简单加密某段内存
// .buffer 目的内存首地址
// .size 目的内存长度
// .key 钥匙，注意：此值必须至少包括一个字符
extern FAPI void FEncodeBuffer(BYTE* buffer, size_t size, ACHAR* key);
// 通过KEY简单解码某段内存
// .buffer 目的内存首地址
// .size 目的内存长度
// .key 钥匙，注意：此值必须至少包括一个字符
extern FAPI void FDecodeBuffer(BYTE* buffer, size_t size, ACHAR* key);
// 将内存数据转为多字节字符串，便于存到数据库
// .mem 数据地址
// .mem_size 数据长度
// .out_size 输出转换后的字符串长度，含\0，可不填
// 返回转换结果字符串首地址，如果mem地址与函数内部缓冲区地址相同则失败
extern FAPI const ACHAR* FMemToDBStr(const BYTE* mem, const size_t mem_size, size_t* out_size);
// 将由上面函数转换的字符串转为内存数据
// .str 字符串首地址，以\0为结束符
// .dst_mem 输出内存地址
// .out_size 输出转换后的内存长度，可不填
// 返回是否转换成功，不成功原因有：str==dst_mem，dst_size容量不足
extern FAPI bool FDBStrToMem(const ACHAR* str, BYTE* dst_mem, size_t dst_size, size_t* out_size);


//----------------------------------------------------------------
// files and path
//----------------------------------------------------------------
// 修复当前exe文件目录为当前目录
//   系统启动默认会执行此接口
//   某些工作调用文件打开功能以后会自动修改当前工作目录，造成一定影响，可以调用此函数修复到EXE工作目录
//   如:MFC的OnOpenDocument和OnSaveDocument，及文件打开对话、目录浏览调用以后
//   安卓环境中指的是xxx.apk路径
//   此接口将影响到FGetRootPath、FGetExePath等这一组接口结果
// .dst 目标目录，如果为0或者空串，将使用默 认程序位置
extern FAPI void FResetCurrentDirectory(const ACHAR* dst = 0);
// 打开文件、保存对话框（仅单选文件）
// .owner 调用窗口，没有则填0
// .ret 输出选择的文件
// .filter 过滤标记，见下面示例
// .title 弹出的对话框标题
// 示例：NCHAR filter[] =
//           _T("ini files (*.ini)\0*.ini\0")
//           _T("All Files (*.*)\0*.*\0");
//       const NCHAR* filename = FFileOpenDialog(AfxGetMainWnd()->GetSafeHwnd(), true, filter);
#if FUEL_OS_WINDOWS
extern FAPI bool FFileOpenDialogW(HWND owner, bool is_save, FStringW& ret, const WCHAR* filter, const WCHAR* title = 0);
extern FAPI bool FFileOpenDialogA(HWND owner, bool is_save, FStringA& ret, const ACHAR* filter, const ACHAR* title = 0);
// 打开文件对话框（多文件选择）
// .out_dir 输出选择的目录
// .out_files 输出选择的目录下面文件列表，需要和out_dir拼接为完整的文件路径
extern FAPI bool FFileOpenDialogMultW(HWND owner, const WCHAR* filter, FStringW& out_dir, FVStringW& out_files);
extern FAPI bool FFileOpenDialogMultA(HWND owner, const ACHAR* filter, FStringA& out_dir, FVStringA& out_files);
// 浏览文件平对话框
extern FAPI bool FBrowserDirDialogW(HWND owner, FStringW& ret, const WCHAR* title = 0);
extern FAPI bool FBrowserDirDialogA(HWND owner, FStringA& ret, const ACHAR* title = 0);
#endif
// 保存一段文本内容到文件
extern FAPI void FSaveTextToFileW(const WCHAR* text, const WCHAR* filename, bool append = true);
extern FAPI void FSaveTextToFileA(const ACHAR* text, const ACHAR* filename, bool append = true);
// 获取指定目录下所有指定类型的文件
// 不包括子目录下的文件，要查询子目录请用FFindFileByPath函数
// .vext 此列表出的类型文件才输出，如果为0全部输出（要带"."点号，如".png"）
#if FUEL_OS_WINDOWS
extern FAPI void FGetDirFilesW(const WCHAR* dir, FVStringW& vout, const FV_PWCHAR* vext = 0);
extern FAPI void FGetDirFilesA(const ACHAR* dir, FVStringA& vout, const FV_PACHAR* vext = 0);
// 获取指定目录下所有文件夹
extern FAPI void FGetDirDirsW(const WCHAR* dir, FVStringW& vout);
extern FAPI void FGetDirDirsA(const ACHAR* dir, FVStringA& vout);
#endif
// 测试是否是引擎支持的图片文件类型
extern FAPI bool FIsSupportPictureW(const WCHAR* path);
extern FAPI bool FIsSupportPictureA(const ACHAR* path);
// 在打开文件对话框中的用于过滤图片文件类型的功能
extern FAPI const WCHAR* FGetSupportPictureFilterW();
extern FAPI const ACHAR* FGetSupportPictureFilterA();
// 支持的图片文件类开扩展名列表（带"."点号，如".png"）
// 示例：fv_ptchar& vext = FGetSupportPictureExt();
extern FAPI const FV_PWCHAR& FGetSupportPictureExtW();
extern FAPI const FV_PACHAR& FGetSupportPictureExtA();
// 获取指定格式的后叠名（带"."点号，如".png"）
extern FAPI const WCHAR* FImageFormatExnameW(EF_IMAGE_FORMAT fmt);
extern FAPI const ACHAR* FImageFormatExnameA(EF_IMAGE_FORMAT fmt);
// 从目录或者APK包中读取文件（WINDOWS下构造中也可以调用。安卓不能全局构造对象时调用，需待APK包初始化完成）
// .gfile 在WINDOWS环境下，file指的是具体的目录位置或者相对路径
//        在ANDROID环境下，file指的是APK的中的assets目录下的某个文件路径
//                         如果在APK包中没有找到该文件，则尝试以android_sd + gfile方式从SD卡上加载
// .buf 输入文件到缓存，如果填0表示测试是件是否存在，在安卓环境下相当于测试文件是否在包里
// .android_sd 只在安卓下有效（可以填空或者0，表示gfile已经是完整SD路径了）
extern FAPI bool FFileReadW(const WCHAR* gfile, FV_BYTE* buf, const WCHAR* android_sd = 0);
extern FAPI bool FFileReadA(const ACHAR* gfile, FV_BYTE* buf, const ACHAR* android_sd = 0);
// 打开文件（标准C文件函数，用法一样。）
extern FAPI FILE* FOpenW(const WCHAR* filename, const WCHAR* mode);
extern FAPI FILE* FOpenA(const ACHAR* filename, const ACHAR* mode);
// 写文件内容
extern FAPI size_t FWrite(const void* src, size_t element_size, size_t element_count, FILE* file);
// 写文件内容
extern FAPI size_t FRead(void* dst, size_t element_size, size_t element_count, FILE* file);
// 定位文件
extern FAPI int FSeek(FILE* file, long offset, int origin);
// 关闭文件
extern FAPI int FClose(FILE*& file);
// 测试文件是否存在
extern FAPI bool FIsExistW(const WCHAR* szpath);
extern FAPI bool FIsExistA(const ACHAR* szpath);
// 测试目录是否存在
extern FAPI bool FIsDirectoryW(const WCHAR* szpath);
extern FAPI bool FIsDirectoryA(const ACHAR* szpath);
// 创建目录树，可以使用文件路径，包括子目录一起自动创建（如果路径全是目录，需在尾部加上\\）
extern FAPI void FMakeDirectoryW(const WCHAR* szpath);
extern FAPI void FMakeDirectoryA(const ACHAR* szpath);
// 删除目录或者文件，包括子文件一起删除
// .szpath 目标文件或者目录
// .go_recycle 是否进回收站，如果false直接删除而不进回车站（WINDOWS支持）
extern FAPI bool FDelDirectoryW(const WCHAR* szpath, bool go_recycle);
extern FAPI bool FDelDirectoryA(const ACHAR* szpath, bool go_recycle);
FINLINE bool FDelFileW(const WCHAR* szpath, bool go_recycle);
FINLINE bool FDelFileA(const ACHAR* szpath, bool go_recycle);
// 重命名文件
extern FAPI void FReNameW(const WCHAR* old_path, const WCHAR* new_path);
extern FAPI void FReNameA(const ACHAR* old_path, const ACHAR* new_path);
// 获取文件尺寸（支持超大文件）
// 如果为-1表示文件不存在，0表示其它失败或者文件本身就是0，大于0则成功
extern FAPI INT64 FFileSizeW(const WCHAR* szpath);
extern FAPI INT64 FFileSizeA(const ACHAR* szpath);
// 取路径的目录
extern FAPI void FFileDirW(const WCHAR* szpath, FStringW& out);
extern FAPI void FFileDirA(const ACHAR* szpath, FStringA& out);
// 获取指定路径的文件名字部分，不带扩展名
extern FAPI FStringW& FFileNameW(const WCHAR* path, FStringW& out_name);
extern FAPI FStringA& FFileNameA(const ACHAR* path, FStringA& out_name);
// WIN32中将中径中的“/”转换为安全的“\\”，否则转为“/”
//    传入为空路径，不处理
// .append_dir_end 如果为true，并且path的尾部没有“\\”自动追加“\\”到尾部
extern FAPI void FConvertToSafePathW(FStringW& path, bool append_dir_end = false);
extern FAPI void FConvertToSafePathA(FStringA& path, bool append_dir_end = false);
// 标准化一条路径，转长完整路径串，并可转为小写，"/"转为"\\"，"~"转为完全路径
// .path 输入与输出结果。
// .return 返回path引用
extern FAPI FStringW& FNormalizeFilepathW(FStringW& path, bool to_lower = true);
extern FAPI FStringA& FNormalizeFilepathA(FStringA& path, bool to_lower = true);
// 从路径中定位文件名位置
// 返回位置，如果没有目录则返回szpath
extern FAPI const WCHAR* FFileNamePositionW(const WCHAR* szpath);
extern FAPI const ACHAR* FFileNamePositionA(const ACHAR* szpath);
// 从路径中定位文件名扩展名位置
// 返回位置，包括符号“.”，如果没有扩展名则返回0
extern FAPI const WCHAR* FFileExtPositionW(const WCHAR* szpath);
extern FAPI const ACHAR* FFileExtPositionA(const ACHAR* szpath);
// 测试文件路径是否是指定扩展名，如果不是自动补充到该扩展名
// .ext 需要带上点，如“.png”、“.dds”
extern FAPI FStringW& FFileExtInspectW(FStringW& str, const WCHAR* ext);
extern FAPI FStringA& FFileExtInspectA(FStringA& str, const ACHAR* ext);
// 修改文件路径的扩展名（失败返回0，成功返回串首地址）
// .filename 源串
// .exname 新的扩展名，例: "txt"，如果填0表示去掉扩展名
extern FAPI const WCHAR* FModifyExnameW(const WCHAR* filename, const WCHAR* exname);
extern FAPI const ACHAR* FModifyExnameA(const ACHAR* filename, const ACHAR* exname);
// 测试两个文件是否相同（不能对APK包中的文件进行比较）
extern FAPI bool FFileDifferentW(const WCHAR* afile, const WCHAR* bfile);
extern FAPI bool FFileDifferentA(const ACHAR* afile, const ACHAR* bfile);
// 测试文本文件类型（TXT/XML/HTML等任何文本文件）
// .file 需要检查的文件
// .head_size 返回该文件的BOM头占用字节数，填0表示不需要返回
// .return 返回相应的测试结果，测试失败返回eEM_MAX，无法确定的时候返回eEM_ANSI
extern FAPI EF_ENCODE_MODE FFileTypeW(const WCHAR* file, size_t* head_size = 0);
extern FAPI EF_ENCODE_MODE FFileTypeA(const ACHAR* file, size_t* head_size = 0);
// 加载文本文件
// .file 需要加载的文件
// .ret 输出到字符串表
// .type 输出该文件的类型，不需返回填0
extern bool FTextFileOpenW(const WCHAR* file, FV_WCHAR& ret, EF_ENCODE_MODE* type);
extern bool FTextFileOpenA(const ACHAR* file, FV_WCHAR& ret, EF_ENCODE_MODE* type);
// 写入文本文件
// .file 目标写入文件
// .txt 文本内容
// .type 目标编码
// .bom_head 非eEM_ANSI情况是否需要加BOM头
extern bool FTextFileWriteW(const WCHAR* file, const WCHAR* txt, EF_ENCODE_MODE type = eEM_ANSI, bool bom_head = true);
extern bool FTextFileWriteA(const ACHAR* file, const WCHAR* txt, EF_ENCODE_MODE type = eEM_ANSI, bool bom_head = true);
// DLL/SO打开
extern FAPI HINSTANCE FDllOpenW(const WCHAR* file);
extern FAPI HINSTANCE FDllOpenA(const ACHAR* file);
// DLL/SO函数获取
extern FAPI void* FDllGetW(HINSTANCE hins, const WCHAR* func_name);
extern FAPI void* FDllGetA(HINSTANCE hins, const ACHAR* func_name);
// DLL/SO关闭
extern FAPI void FDllClose(HINSTANCE& hins);


//----------------------------------------------------------------
// strings
//----------------------------------------------------------------
// 字符串转整型
FINLINE int FAtoiW(const WCHAR* str);
FINLINE int FAtoiA(const ACHAR* str);
// 字符串转符点数
FINLINE float FAtofW(const WCHAR* str);
FINLINE float FAtofA(const ACHAR* str);
// 字符串转双精度符点数
FINLINE double FAtodW(const WCHAR* str);
FINLINE double FAtodA(const ACHAR* str);
// 字符串完整比较
FINLINE int FStrcmpW(const WCHAR* left, const WCHAR* right);
FINLINE int FStrcmpA(const ACHAR* left, const ACHAR* right);
// 字符串比较,不定数量,不区分大小写
FINLINE int FStricmpW(const WCHAR* left, const WCHAR* right);
FINLINE int FStricmpA(const ACHAR* left, const ACHAR* right);
// 字符串比较,指定数量,区分大小写
FINLINE int FStrncmpW(const WCHAR* left, const WCHAR* right, size_t comp_count);
FINLINE int FStrncmpA(const ACHAR* left, const ACHAR* right, size_t comp_count);
// 字符串比较,指定数量,不区分大小写
FINLINE int FStrnicmpW(const WCHAR* left, const WCHAR* right, size_t comp_count);
FINLINE int FStrnicmpA(const ACHAR* left, const ACHAR* right, size_t comp_count);
// 字符串长度
FINLINE size_t FStrlenW(const WCHAR* s);
FINLINE size_t FStrlenA(const ACHAR* s);
// UTF8的字符串长度
extern FAPI int FStrlenUTF8(const ACHAR* s);
// 指定串区间的串长度
extern FAPI size_t FStrnlenW(const WCHAR* wcs, size_t maxsize);
extern FAPI size_t FStrnlenA(const ACHAR* str, size_t maxsize);
// 用于非WINDOWS系统的宽字符比较，忽略大小写
extern FAPI int FStrcasecmpW(const WCHAR *s1, const WCHAR *s2);
extern FAPI int FStrncasecmpW(const WCHAR *s1, const WCHAR *s2, size_t n);
// 将串转为大写
extern FAPI WCHAR* FStrToUpperW(WCHAR* str);
extern FAPI ACHAR* FStrToUpperA(ACHAR* str);
// 将串转为小写
extern FAPI WCHAR* FStrToLowerW(WCHAR* str);
extern FAPI ACHAR* FStrToLowerA(ACHAR* str);
// 字符大小写转换
// .cov_type 转换类型：0不转换，1转为小写，2转为大写（非英文字符不处理）
FINLINE WCHAR FConvertCharW(WCHAR k, BYTE cov_type = 0);
FINLINE ACHAR FConvertCharA(ACHAR k, BYTE cov_type = 0);
// 字符串复制（支持中文，支持UNICODE和多字节，不支持UTF8）
// .size dst能容纳字符数量（不是内存大小）
// .cov_type 转换类型：0不转换，1转为小写，2转为大写（非英文字符不处理）
extern FAPI ACHAR* FStrcpyA_s(ACHAR* dst, const ACHAR* src, size_t size, BYTE cov_type = 0);
extern FAPI WCHAR* FStrcpyW_s(WCHAR* dst, const WCHAR* src, size_t size, BYTE cov_type = 0);
template < size_t size > FINLINE ACHAR* FStrcpyA(ACHAR (&dst)[size], const ACHAR* src, BYTE cov_type = 0);
template < size_t size > FINLINE WCHAR* FStrcpyW(WCHAR (&dst)[size], const WCHAR* src, BYTE cov_type = 0);
// 字符串补充
extern FAPI ACHAR* FStrcatA_s(ACHAR* dst, const ACHAR* src, size_t size, BYTE cov_type = 0);
extern FAPI WCHAR* FStrcatW_s(WCHAR* dst, const WCHAR* src, size_t size, BYTE cov_type = 0);
template < size_t size > FINLINE ACHAR* FStrcatA(ACHAR (&dst)[size], const ACHAR* src, BYTE cov_type = 0);
template < size_t size > FINLINE WCHAR* FStrcatW(WCHAR (&dst)[size], const WCHAR* src, BYTE cov_type = 0);
// 搜索字符, 从头至尾搜索, 找到'\0'结束
extern FAPI const WCHAR* FStrchrW(const WCHAR* src, WCHAR chr);
extern FAPI const ACHAR* FStrchrA(const ACHAR* src, ACHAR chr);
// 搜索字符, 从头至尾搜索, 并只搜索指定数量范围, 以宽字符或者字节为单位
FINLINE const WCHAR* FMemchrW(const WCHAR* src, WCHAR chr, size_t count);
FINLINE const ACHAR* FMemchrA(const ACHAR* src, ACHAR chr, size_t count);
// 将字符串转换为C++能识别的符号名，如“E:\\A.png”转换为“E__A_png”
// .str 输入字符，并输出转换结果
// .check_first 是否检查首字符是否有效
extern FAPI void FStrName_cplusplusW(WCHAR* str, bool check_first = true);
extern FAPI void FStrName_cplusplusA(ACHAR* str, bool check_first = true);
// 测试字符串是不是只有数字、英文字母、和下划线，以及长度要求（且首字只能是英文字母）
// .str 检测串
// .need_size 同时字符数量必须满足此要求
// .check_length 指定检查输入字符数量，不可填0
extern FAPI bool FStrName_checkW(const WCHAR* str, const size_t need_size = 2, const size_t check_length = 0xffff);
extern FAPI bool FStrName_checkA(const ACHAR* str, const size_t need_size = 2, const size_t check_length = 0xffff);
// 字符串名字加法（如：name1 改为 name2，wk59 改为 wk60）
extern FAPI FStringW& FStrName_addW(FStringW& name);
extern FAPI FStringA& FStrName_addA(FStringA& name);
// 字符串长度截断，以点点节尾
// .s 输入和输出字符串结果
// .w 字体需要显示的象素宽度
// .dot_count 后面带的点数量
class IFStrClipQuery;
extern FAPI const WCHAR* FStrClipW(FStringW& s, IFStrClipQuery* query, size_t w, int dot_count);
extern FAPI const ACHAR* FStrClipA(FStringA& s, IFStrClipQuery* query, size_t w, int dot_count);
// 是否是Base64字符
extern FAPI bool FIsBase64Char(BYTE c);
// 将多字节字符串转为Base64字符集，不支持中文
extern FAPI FStringA& FToBase64String(FStringA& dst, const BYTE* src, size_t src_len);
// 将Base64字符集转多字节字符串，不支持中文
extern FAPI FStringA& FFromBase64String(FStringA& dst, FStringA& src);
// 获取字符集类型的字符串描述
extern FAPI const ACHAR* FGetCharEncodeName(EF_ENCODE_MODE em);
// 获取字符集类型对应的一个字符所点内存宽度
extern FAPI size_t FGetCharEncodeSize(EF_ENCODE_MODE em);
// 多字节与宽字节字符相互转换
// .src_em,dstem 各平台之间默认的编码模式
// .dst 输出后的尾部带有\0，字符串长度为取dst.size()-1
extern FAPI void FWStrToAStr(const WCHAR* src, FV_ACHAR& dst, EF_ENCODE_MODE src_em = FUEL_EC_WCHAR, EF_ENCODE_MODE dst_em = FUEL_EC_ACHAR);
extern FAPI void FAStrToWStr(const ACHAR* src, FV_WCHAR& dst, EF_ENCODE_MODE src_em = FUEL_EC_ACHAR, EF_ENCODE_MODE dst_em = FUEL_EC_WCHAR);
// 取得多字节与宽字节转换后所需的内存长度，
extern FAPI int FWStrLength(const ACHAR* src);
extern FAPI int FAStrLength(const WCHAR* src);
// 不安全的字符串转换，需要自己确保安全
extern FAPI void FWStrToAStrNS(const WCHAR* src, ACHAR* dst);
extern FAPI void FAStrToWStrNS(const ACHAR* src, WCHAR* dst);
// 将多字节字符串转为UTF8字符串，支持中文（GB2312 -> UTF8）
// .return 返回dst串
extern FAPI FStringA& FANSIToUTF8(FStringA& dst_utf8, const ACHAR* src_ansi);
extern FAPI const ACHAR* FANSIToUTF8_EX(const ACHAR* src_ansi);
// 将UTF8字符串转为多字节字符串，支持中文（UTF8 -> GB2312）
// .return 返回dst串
extern FAPI FStringA& FUTF8ToANSI(FStringA& dst_ansi, const ACHAR* src_utf8);
extern FAPI const ACHAR* FUTF8ToANSI_EX(const ACHAR* src_utf8);
// 将多字节字符串转为宽字节字符串，支持中文（GB2312 -> UTF16LE/UTF32LE）
//   当WCHAR是2字节时目录为UTF16LE，否则是UTF32LE
// .return 返回dst串
extern FAPI FStringW& FANSIToUNICODE(FStringW& dst_unicode, const ACHAR* src_ansi);
extern FAPI const WCHAR* FANSIToUNICODE_EX(const ACHAR* src_ansi);
// 将宽字节字符串转为多字节字符串，支持中文（UTF16LE/UTF32LE -> GB2312）
//   当WCHAR是2字节时目录为UTF16LE，否则是UTF32LE
// .return 返回dst串
extern FAPI FStringA& FUNICODEToANSI(FStringA& dst_ansi, const WCHAR* src_unicode);
extern FAPI const ACHAR* FUNICODEToANSI_EX(const WCHAR* src_unicode);
// 将UTF8字符串转为宽字节字符串，支持中文（UTF8 -> UTF16LE/UTF32LE）
//   当WCHAR是2字节时目录为UTF16LE，否则是UTF32LE
// .return 返回dst串
extern FAPI FStringW& FUTF8ToUNICODE(FStringW& dst_unicode, const ACHAR* src_utf8);
extern FAPI const WCHAR* FUTF8ToUNICODE_EX(const ACHAR* src_utf8);
// 将宽字节字符串转为UTF8字符串，支持中文（UTF16LE/UTF32LE -> UTF8）
//   当WCHAR是2字节时目录为UTF16LE，否则是UTF32LE
// .return 返回dst串
extern FAPI FStringA& FUNICODEToUTF8(FStringA& dst_utf8, const WCHAR* src_unicode);
extern FAPI const ACHAR* FUNICODEToUTF8_EX(const WCHAR* src_unicode);
// 从字符串中分析数据到字符串容器
// .vout 输出串列表
// .combo_str 组合串，以"|"分格，并以"|"结束。（格式：_FT("普通|全局|静态|")）
// .only_first 是否只处理第一个串
// .return 返回第一个串的首地址
extern FAPI const WCHAR* FComboStringW(FVStringW& vout, const WCHAR* combo_str, bool only_first = false);
extern FAPI const ACHAR* FComboStringA(FVStringA& vout, const ACHAR* combo_str, bool only_first = false);
// 从字符串转为对应的类型数值，请自主控制函数的安全性
// .cur_str 当前串的值
// .ty_list 整个类型表，数量需要和combo_str的格式里所含的串数量一致
// .combo_str 组合串，见FComboString函数说明
template < typename _Ty >
FINLINE _Ty FComboStringToTypeW(const WCHAR* cur_str, const _Ty* ty_list, const WCHAR* combo_str);
template < typename _Ty >
FINLINE _Ty FComboStringToTypeA(const ACHAR* cur_str, const _Ty* ty_list, const ACHAR* combo_str);
// 从组合串中查询指定的类型
template < typename _Ty > 
FINLINE const WCHAR* FComboStringToStrW(FStringW& ret, _Ty cur_str, const _Ty* ty_list, const WCHAR* combo_str);
template < typename _Ty > 
FINLINE const ACHAR* FComboStringToStrA(FStringA& ret, _Ty cur_str, const _Ty* ty_list, const ACHAR* combo_str);


//----------------------------------------------------------------
// other functions
//----------------------------------------------------------------
// 生成FGUID
struct FGUID;
#if FUEL_OS_WINDOWS
extern FAPI void FGetFGUID(FGUID* out_id);
// FGUID转为标准GUID字符串，如：“12E6E3C9-512F-42FA-A1A5-0991994B7D7C”
// .id 如果填0则自动生成，否则按传入值输出格式化串
extern FAPI void FGUIDToStringW(FGUID* id, FStringW& out);
extern FAPI void FGUIDToStringA(FGUID* id, FStringA& out);
// 测试某个按键是否按下
// .hwnd 当前活动窗口句柄，如果填0表示全局按钮测试
// .vk 按键码
extern FAPI bool FIsKeyDown(HWND hwnd, DWORD vk);
// 获取系统状态查询器地址
class IFSystem;
extern FAPI IFSystem* FGetSystemQuery();
// 释放系统状态查询器（如果你不释放，那么在关闭程序以后会自动释放）
extern FAPI void FReleaseSystemQuery();
#endif
// 创建一个线程
// .stack_size 线程栈大小，0：系统控制默认大小
// .func 函数地址
// .parameter 线程参数
// .initflag 创建参数，0：立即运行，CREATE_SUSPENDED：暂停
// 返回线程句柄
struct FTHREAD_DATA
{
    HANDLE handle;
    DWORD attr;
    DWORD id;
};
typedef UINT (FCALL *FThreadFunc)(void* parameter);
typedef void* (FCALL *FThreadFunc_pt)(void * parameter);
extern FAPI HANDLE FCreateThread(size_t stack_size, FThreadFunc func, void* parameter = 0, DWORD initflag = 0);
// 线程函数内部结束时调用，不清理数据，直接退出
extern FAPI void FExitThread(UINT code = 0);
// 获取主线程ID
extern FAPI DWORD FGetMainThreadID();
// 取当前线程ID
extern FAPI DWORD FGetCurrentThreadID();
// 挂起一个正在运行的线程
extern FAPI DWORD FSuspendThread(HANDLE hand);
// 恢复一个挂起的线程
extern FAPI DWORD FResumeThread(HANDLE hand);
// 强制杀死一个线程（不安全，会造成内存泄露）
extern FAPI BOOL FTerminateThread(HANDLE hand);
// 等待一个线程的结束
// .hand 将要关闭的线程句柄
// .cmd 该线程的命令地址，此函数会给线程函数命令设置为eTC_Exit
extern FAPI void FWaitThreadEnd(HANDLE& hand, EF_THREAD_COMMAND& cmd);
// 获取系统线程地址（不直接使用此函数，由线程对象自动调用）
extern FAPI FThreadFunc FGetThreadEngine();
#if FUEL_OS_WINDOWS
// 开启此进程的剪贴板功能（如果任何剪贴板功能失败，则调用一次些函数即可）
extern FAPI void FEnableClipboard(HWND hwnd);
// 设置剪贴板内容（如果此函数调用失败请先调用FEnableClipboard函数）
// .pdata 需要设置的内容
// .length 内容长度
// .type ANSI时填CF_TEXT，UNICODE时填CF_UNICODETEXT，其它按需填写
extern FAPI bool FSetClipboardData(const BYTE* pdata, size_t length, DWORD type = CF_TEXT);
// 从剪贴板中获取内容
// .length 返回数据长度
// 返回数据首地址
extern FAPI BYTE* FGetClipboardData(size_t& length, DWORD type = CF_TEXT);
// 格式化WINDOWS错误信息
extern FAPI const WCHAR* FGetSysErrorStringW(DWORD error_id = GetLastError());
extern FAPI const ACHAR* FGetSysErrorStringA(DWORD error_id = GetLastError());
// 初始化COM（可多次配对调用）
extern FAPI void FCoInitialize();
// 关闭COM（可多次配对调用）
extern FAPI void FCoUninitialize();
#endif
// 取得CPU时钟频率
extern FAPI INT64 FGetCPUTicksPerSec();
// 取得当前的CPU时间（单位纳秒）
extern FAPI INT64 FGetCPUTime();
// LINUX下将时间转为纳秒
extern FAPI INT64 FTimeToNS(FTIMEVAL& t);
// 暂停，释放时间片（单位毫秒）
extern FAPI void FSleep(DWORD n);
// 某个值是否在另一个表中出现过
template < typename _Ty >
FINLINE bool FHasThis(const _Ty& a, const _Ty* b, size_t b_size);
// 通过总帧数转为时间，单位毫秒
extern FAPI DWORD FFrameToTime(DWORD frame_count, int freq);
// 启动一个外部程序，或者打开网页
//   打开文件：FShellExecute(fge->GetHwnd(), file, SW_SHOWNORMAL);
//   浏览目录（需要'\'结尾）：FShellExecute(ghr->GetHwnd(), path, SW_SHOWNORMAL, _FT("explore"));
#if FUEL_OS_WINDOWS
extern FAPI HINSTANCE FShellExecuteW(HWND hwnd, const WCHAR* filename, DWORD mode, const WCHAR* lpOperation = 0);
extern FAPI HINSTANCE FShellExecuteA(HWND hwnd, const ACHAR* filename, DWORD mode, const ACHAR* lpOperation = 0);
// Fuel4D 工具用于生成关于对话框的文本
extern FAPI const WCHAR* FAboutToolW(const WCHAR* tool_name);
extern FAPI const ACHAR* FAboutToolA(const ACHAR* tool_name);
#endif
// 获取当前的系统时间，即函数_time32(0)
extern FAPI FTIME_T FTime32();
struct FDATE_TIME
{
    int tm_sec;     /* seconds after the minute - [0,59] */
    int tm_min;     /* minutes after the hour - [0,59] */
    int tm_hour;    /* hours since midnight - [0,23] */
    int tm_mday;    /* day of the month - [1,31] */
    int tm_mon;     /* months since January - [0,11] */
    int tm_year;    /* years since 具体某一个，不是1900以来的年数*/
    int tm_wday;    /* days since Sunday - [0,6] */
    int tm_yday;    /* days since January 1 - [0,365] */
    int tm_isdst;   /* daylight savings time flag */
};
// 获取当前的时间日期信息
extern FAPI void FGetDateTime(FDATE_TIME& ret);
// 将指定32位TIME_T转为日期时间格式
extern FAPI void FGetLocalTime(FTIME_T nt, FDATE_TIME& out);
// 取得指定年指定月的自然天数
// .return 如果失败返回0
extern FAPI int FGetDaysByYearMonth(WORD year, BYTE month);
// 取得当前日期（年-月-日）
extern FAPI const WCHAR* FGetDateStrW(FStringW& str, const WCHAR delimited = _FTW('-'));
extern FAPI const WCHAR* FGetDateCharW(WCHAR (&dst)[12], const WCHAR delimited = _FTW('-'));
extern FAPI const ACHAR* FGetDateStrA(FStringA& str, const ACHAR delimited = _FTA('-'));
extern FAPI const ACHAR* FGetDateCharA(ACHAR (&dst)[12], const ACHAR delimited = _FTA('-'));
// 取得当前时间（时:分:秒）
extern FAPI const WCHAR* FGetTimeStrW(FStringW& str, const WCHAR delimited = _FTW(':'));
extern FAPI const WCHAR* FGetTimeCharW(WCHAR (&dst)[12], const WCHAR delimited = _FTW(':'));
extern FAPI const ACHAR* FGetTimeStrA(FStringA& str, const ACHAR delimited = _FTA(':'));
extern FAPI const ACHAR* FGetTimeCharA(ACHAR (&dst)[12], const ACHAR delimited = _FTA(':'));
// 打印错误消息到文件，同时弹出错误提示，并返回false
// 注意：debug模式下会弹出提示，release仅打印到文件
extern FAPI bool FPrintErrorMessageW(const WCHAR* str);
extern FAPI bool FPrintErrorMessageA(const ACHAR* str);
// 从字体象素大小转为LOGFONT字体高度
#if FUEL_OS_WINDOWS
extern FAPI LONG FGetLFHeightByFntSize(BYTE fnt_size, int bpi = 72);
// 从LOGFONT字体高度转换为字体象素大小
extern FAPI BYTE FGetFntSizeByLFHeight(LONG lH, int bpi = 72);
extern FAPI void FInitGDIPlus();
// GDI+中查询指定的图片格式CLSID
extern FAPI bool FGetEncoderClsid(const WCHAR* format, CLSID* pClsid);
// 生成验证码图片，注意：调用函数用前需初始化GDI+
// .out_buf 输出数据地址，它对应的数据长度应该为picw*pich字节，格式为ARGB
// .picw,pich 输出图片尺寸，注意：最小尺寸是32x32
// .ncode 输入验证码字符串
// .char_count 验证码字符数量
// .color 字符颜色表
// .color_count 颜色数量
// .save_path 调试用。保存结果到PNG文件，为0时不保存文件
extern FAPI bool FGenVerifyPictureW(DWORD* out_buf, int picw, int pich, const WCHAR* ncode, size_t char_count,
	DWORD* color, size_t color_count, const WCHAR* save_path);
extern FAPI bool FGenVerifyPictureA(DWORD* out_buf, int picw, int pich, const ACHAR* ncode, size_t char_count,
    DWORD* color, size_t color_count, const ACHAR* save_path);
#endif


//----------------------------------------------------------------
// 屏蔽字过滤系统
//----------------------------------------------------------------
// 初始化字符串过滤器，允许“\r”“\n”，但回车换符号不会截断一个屏蔽词，如：“你妈/去死/共产党/SB/这是一\r\n个词/”
// .buf 过滤文件或者缓存数据，不区分大小写，以“/”分隔，要以分符作为结束
// .size 过滤数据串长度
// .compart 每个过滤词之间的分隔符，只能1个字符
// .muster_id 过滤集合ID，最大支持eCD_MaxFiltrate个集合
// .append_mode 是否是追加模式，如果不是追则会先清掉该过滤集
extern FAPI bool FStrFiltrateInitW(const WCHAR* buf, size_t size, const WCHAR compart = _FTW('/'), BYTE muster_id = 0, bool append_mode = false);
extern FAPI bool FStrFiltrateInitA(const ACHAR* buf, size_t size, const ACHAR compart = _FTA('/'), BYTE muster_id = 0, bool append_mode = false);
// 过滤字符串，通过字符串过滤过进行过滤
extern FAPI bool FStrFiltrateW(WCHAR* src, size_t src_len, BYTE muster_id = 0);
extern FAPI bool FStrFiltrateA(ACHAR* src, size_t src_len, BYTE muster_id = 0);


//----------------------------------------------------------------
// color
//----------------------------------------------------------------
// 组合颜色值
FINLINE DWORD FARGB(BYTE a, BYTE r, BYTE g, BYTE b)
{
    return ((DWORD(a)<<24) | (DWORD(r)<<16) | (DWORD(g)<<8) | DWORD(b));
}
// 组合颜色值（符点数）
FINLINE DWORD FARGBF(float a, float r, float g, float b)
{
    DWORD ret = 0;
    ret |= (((DWORD)(a*255.0f)) & 0xFF)<<24;
    ret |= (((DWORD)(r*255.0f)) & 0xFF)<<16;
    ret |= (((DWORD)(g*255.0f)) & 0xFF)<<8;
    ret |= (((DWORD)(b*255.0f)) & 0xFF);
    return ret;
}
// 分解颜色值
FINLINE DWORD FGetA(DWORD col) { return ((col)>>24) & 0xFF; }
FINLINE DWORD FGetR(DWORD col) { return ((col)>>16) & 0xFF; }
FINLINE DWORD FGetG(DWORD col) { return ((col)>>8 ) & 0xFF; }
FINLINE DWORD FGetB(DWORD col) { return ((col)    ) & 0xFF; }
// 设置颜色值
FINLINE DWORD FSetA(DWORD col, BYTE a) { return (((col) & 0x00FFFFFF) | (DWORD(a)<<24)); }
FINLINE DWORD FSetR(DWORD col, BYTE r) { return (((col) & 0xFF00FFFF) | (DWORD(r)<<16)); }
FINLINE DWORD FSetG(DWORD col, BYTE g) { return (((col) & 0xFFFF00FF) | (DWORD(g)<<8 )); }
FINLINE DWORD FSetB(DWORD col, BYTE b) { return (((col) & 0xFFFFFF00) | (DWORD(b)    )); }
// 分解颜色值（符点数）
FINLINE float FGetAF(DWORD argb) { return F_1BY255 * (float)((BYTE)(argb>>24)); }
FINLINE float FGetRF(DWORD argb) { return F_1BY255 * (float)((BYTE)(argb>>16)); }
FINLINE float FGetGF(DWORD argb) { return F_1BY255 * (float)((BYTE)(argb>> 8)); }
FINLINE float FGetBF(DWORD argb) { return F_1BY255 * (float)((BYTE)(argb    )); }
// 颜色混合
extern FAPI DWORD FBlendColor(float alpha, DWORD color);
// 颜色安全夹
FINLINE void FColorClamp(float &x)
{
    if (x < 0.0f)
        x = 0.0f;
    if (x > 1.0f)
        x = 1.0f;
}
// GDI的颜色转换
FINLINE DWORD FCOLORREF2ARGB(COLORREF cref, DWORD alpha = 0xFF000000)
{
    DWORD argb = alpha;
    argb |= (cref & 0x000000FF)<<16;
    argb |= (cref & 0x0000FF00);
    argb |= (cref & 0x00FF0000)>>16;
    return argb;
}
// GDI的颜色转换
FINLINE COLORREF FARGB2COLORREF(DWORD argb)
{
    COLORREF cref = 0;
    cref |= (argb & 0x00FF0000)>>16;
    cref |= (argb & 0x0000FF00);
    cref |= (argb & 0x000000FF)<<16;
    return cref;
}
// 颜色平面插值
// c1,c2,c3,c4 分别代表左上、左下、右上、右下四个点
// xt,yt 分别代表在x、y轴上面的强度，以左上角为起点
extern FAPI DWORD FARGBSlerp(DWORD c1, DWORD c2, DWORD c3, DWORD c4, float xt, float yt);


//----------------------------------------------------------------
//
//----------------------------------------------------------------
#ifdef UNICODE
#define FGetRootPath                FGetRootPathW
#define FGetExePath                 FGetExePathW
#define FGetExeFilename             FGetExeFilenameW
#define FOutDebugStr                FOutDebugStrW
#define FOutDebugString             FOutDebugStringW
#define FSaveTextToFile             FSaveTextToFileW
#define FGetHash                    FGetHashW
#define FGetHash64                  FGetHash64W
#define FGetDateStr                 FGetDateStrW
#define FGetDateChar                FGetDateCharW
#define FGetTimeStr                 FGetTimeStrW
#define FGetTimeChar                FGetTimeCharW
#define FFileOpenDialog             FFileOpenDialogW
#define FFileOpenDialogMult         FFileOpenDialogMultW
#define FBrowserDirDialog           FBrowserDirDialogW
#define FGetDirFiles                FGetDirFilesW
#define FGetDirDirs                 FGetDirDirsW
#define FIsSupportPicture           FIsSupportPictureW
#define FGetSupportPictureFilter    FGetSupportPictureFilterW
#define FGetSupportPictureExt       FGetSupportPictureExtW
#define FImageFormatExname          FImageFormatExnameW
#define FFileRead                   FFileReadW
#define FOpen                       FOpenW
#define FIsExist                    FIsExistW
#define FIsDirectory                FIsDirectoryW
#define FMakeDirectory              FMakeDirectoryW
#define FDelDirectory               FDelDirectoryW
#define FDelFile                    FDelFileW
#define FReName                     FReNameW
#define FFileSize                   FFileSizeW
#define FFileDir                    FFileDirW
#define FFileName                   FFileNameW
#define FConvertToSafePath          FConvertToSafePathW
#define FNormalizeFilepath          FNormalizeFilepathW
#define FFileNamePosition           FFileNamePositionW
#define FFileExtPosition            FFileExtPositionW
#define FFileExtInspect             FFileExtInspectW
#define FModifyExname               FModifyExnameW
#define FFileDifferent              FFileDifferentW
#define FFileType                   FFileTypeW
#define FTextFileOpen               FTextFileOpenW
#define FTextFileWrite              FTextFileWriteW
#define FDllOpen                    FDllOpenW
#define FDllGet                     FDllGetW
#define FAtoi                       FAtoiW
#define FAtof                       FAtofW
#define FAtod                       FAtodW
#define FStrcmp                     FStrcmpW
#define FStrncmp                    FStrncmpW
#define FStricmp                    FStricmpW
#define FStrnicmp                   FStrnicmpW
#define FStrlen                     FStrlenW
#define FStrnlen                    FStrnlenW
#define FStrToUpper                 FStrToUpperW
#define FStrToLower                 FStrToLowerW
#define FConvertChar                FConvertCharW
#define FStrcpy_s                   FStrcpyW_s
#define FStrcpy                     FStrcpyW
#define FStrcat_s                   FStrcatW_s
#define FStrcat                     FStrcatW
#define FStrchr                     FStrchrW
#define FMemchr                     FMemchrW
#define FStrName_cplusplus          FStrName_cplusplusW
#define FStrName_check              FStrName_checkW
#define FStrName_add                FStrName_addW
#define FStrClip                    FStrClipW
#define FTCHARToUTF8                FUNICODEToUTF8
#define FUTF8ToTCHAR                FUTF8ToUNICODE
#define FComboString                FComboStringW
#define FComboStringToType          FComboStringToTypeW
#define FComboStringToStr           FComboStringToStrW
#define FGUIDToString               FGUIDToStringW
#define FGetSysErrorString          FGetSysErrorStringW
#define FShellExecute               FShellExecuteW
#define FAboutTool                  FAboutToolW
#define FPrintErrorMessage          FPrintErrorMessageW
#define FGenVerifyPicture           FGenVerifyPictureW
#define FStrFiltrateInit            FStrFiltrateInitW
#define FStrFiltrate                FStrFiltrateW
#else
#define FGetRootPath                FGetRootPathA
#define FGetExePath                 FGetExePathA
#define FGetExeFilename             FGetExeFilenameA
#define FOutDebugStr                FOutDebugStrA
#define FOutDebugString             FOutDebugStringA
#define FSaveTextToFile             FSaveTextToFileA
#define FGetHash                    FGetHashA
#define FGetHash64                  FGetHash64A
#define FGetDateStr                 FGetDateStrA
#define FGetDateChar                FGetDateCharA
#define FGetTimeStr                 FGetTimeStrA
#define FGetTimeChar                FGetTimeCharA
#define FFileOpenDialog             FFileOpenDialogA
#define FFileOpenDialogMult         FFileOpenDialogMultA
#define FBrowserDirDialog           FBrowserDirDialogA
#define FGetDirFiles                FGetDirFilesA
#define FGetDirDirs                 FGetDirDirsA
#define FIsSupportPicture           FIsSupportPictureA
#define FGetSupportPictureFilter    FGetSupportPictureFilterA
#define FGetSupportPictureExt       FGetSupportPictureExtA
#define FImageFormatExname          FImageFormatExnameA
#define FFileRead                   FFileReadA
#define FOpen                       FOpenA
#define FIsExist                    FIsExistA
#define FIsDirectory                FIsDirectoryA
#define FMakeDirectory              FMakeDirectoryA
#define FDelDirectory               FDelDirectoryA
#define FDelFile                    FDelFileA
#define FReName                     FReNameA
#define FFileSize                   FFileSizeA
#define FFileDir                    FFileDirA
#define FFileName                   FFileNameA
#define FConvertToSafePath          FConvertToSafePathA
#define FNormalizeFilepath          FNormalizeFilepathA
#define FFileNamePosition           FFileNamePositionA
#define FFileExtPosition            FFileExtPositionA
#define FFileExtInspect             FFileExtInspectA
#define FModifyExname               FModifyExnameA
#define FFileDifferent              FFileDifferentA
#define FFileType                   FFileTypeA
#define FTextFileOpen               FTextFileOpenA
#define FTextFileWrite              FTextFileWriteA
#define FDllOpen                    FDllOpenA
#define FDllGet                     FDllGetA
#define FAtoi                       FAtoiA
#define FAtof                       FAtofA
#define FAtod                       FAtodA
#define FStrcmp                     FStrcmpA
#define FStrncmp                    FStrncmpA
#define FStricmp                    FStricmpA
#define FStrnicmp                   FStrnicmpA
#define FStrlen                     FStrlenA
#define FStrnlen                    FStrnlenA
#define FStrToUpper                 FStrToUpperA
#define FStrToLower                 FStrToLowerA
#define FConvertChar                FConvertCharA
#define FStrcpy_s                   FStrcpyA_s
#define FStrcpy                     FStrcpyA
#define FStrcat_s                   FStrcatA_s
#define FStrcat                     FStrcatA
#define FStrchr                     FStrchrA
#define FMemchr                     FMemchrA
#define FStrName_cplusplus          FStrName_cplusplusA
#define FStrName_check              FStrName_checkA
#define FStrName_add                FStrName_addA
#define FStrClip                    FStrClipA
#define FTCHARToUTF8                FANSIToUTF8
#define FUTF8ToTCHAR                FUTF8ToANSI
#define FComboString                FComboStringA
#define FComboStringToType          FComboStringToTypeA
#define FComboStringToStr           FComboStringToStrA
#define FGUIDToString               FGUIDToStringA
#define FGetSysErrorString          FGetSysErrorStringA
#define FShellExecute               FShellExecuteA
#define FAboutTool                  FAboutToolA
#define FPrintErrorMessage          FPrintErrorMessageA
#define FGenVerifyPicture           FGenVerifyPictureA
#define FStrFiltrateInit            FStrFiltrateInitA
#define FStrFiltrate                FStrFiltrateA
#endif

#if FUEL_OS_WINDOWS
#define FFGetRootPath               FGetRootPathW
#define FFGetExePath                FGetExePathW
#define FFGetExeFilename            FGetExeFilenameW
#define FFOutDebugStr               FOutDebugStrW
#define FFOutDebugString            FOutDebugStringW
#define FFSaveTextToFile            FSaveTextToFileW
#define FFGetHash                   FGetHashW
#define FFGetHash64                 FGetHash64W
#define FFGetDateStr                FGetDateStrW
#define FFGetDateChar               FGetDateCharW
#define FFGetTimeStr                FGetTimeStrW
#define FFGetTimeChar               FGetTimeCharW
#define FFFileOpenDialog            FFileOpenDialogW
#define FFFileOpenDialogMult        FFileOpenDialogMultW
#define FFBrowserDirDialog          FBrowserDirDialogW
#define FFGetDirFiles               FGetDirFilesW
#define FFGetDirDirs                FGetDirDirsW
#define FFIsSupportPicture          FIsSupportPictureW
#define FFGetSupportPictureFilter   FGetSupportPictureFilterW
#define FFGetSupportPictureExt      FGetSupportPictureExtW
#define FFImageFormatExname         FImageFormatExnameW
#define FFFileRead                  FFileReadW
#define FFOpen                      FOpenW
#define FFIsExist                   FIsExistW
#define FFIsDirectory               FIsDirectoryW
#define FFMakeDirectory             FMakeDirectoryW
#define FFDelDirectory              FDelDirectoryW
#define FFDelFile                   FDelFileW
#define FFReName                    FReNameW
#define FFFileSize                  FFileSizeW
#define FFFileDir                   FFileDirW
#define FFFileName                  FFileNameW
#define FFConvertToSafePath         FConvertToSafePathW
#define FFNormalizeFilepath         FNormalizeFilepathW
#define FFFileNamePosition          FFileNamePositionW
#define FFFileExtPosition           FFileExtPositionW
#define FFFileExtInspect            FFileExtInspectW
#define FFModifyExname              FModifyExnameW
#define FFFileDifferent             FFileDifferentW
#define FFFileType                  FFileTypeW
#define FFTextFileOpen              FTextFileOpenW
#define FFTextFileWrite             FTextFileWriteW
#define FFDllOpen                   FDllOpenW
#define FFDllGet                    FDllGetW
#define FFAtoi                      FAtoiW
#define FFAtof                      FAtofW
#define FFAtod                      FAtodW
#define FFStrcmp                    FStrcmpW
#define FFStrncmp                   FStrncmpW
#define FFStricmp                   FStricmpW
#define FFStrnicmp                  FStrnicmpW
#define FFStrlen                    FStrlenW
#define FFStrnlen                   FStrnlenW
#define FFStrToUpper                FStrToUpperW
#define FFStrToLower                FStrToLowerW
#define FFConvertChar               FConvertCharW
#define FFStrcpy_s                  FStrcpyW_s
#define FFStrcpy                    FStrcpyW
#define FFStrcat_s                  FStrcatW_s
#define FFStrcat                    FStrcatW
#define FFStrchr                    FStrchrW
#define FFMemchr                    FMemchrW
#define FFStrName_cplusplus         FStrName_cplusplusW
#define FFStrName_check             FStrName_checkW
#define FFStrName_add               FStrName_addW
#define FFStrClip                   FStrClipW
#define FFTCHARToUTF8               FUNICODEToUTF8
#define FFUTF8ToTCHAR               FUTF8ToUNICODE
#define FFComboString               FComboStringW
#define FFComboStringToType         FComboStringToTypeW
#define FFComboStringToStr          FComboStringToStrW
#define FFGUIDToString              FGUIDToStringW
#define FFGetSysErrorString         FGetSysErrorStringW
#define FFShellExecute              FShellExecuteW
#define FFAboutTool                 FAboutToolW
#define FFPrintErrorMessage         FPrintErrorMessageW
#define FFGenVerifyPicture          FGenVerifyPictureW
#define FFStrFiltrateInit           FStrFiltrateInitW
#define FFStrFiltrate               FStrFiltrateW
#else
#define FFGetRootPath               FGetRootPathA
#define FFGetExePath                FGetExePathA
#define FFGetExeFilename            FGetExeFilenameA
#define FFOutDebugStr               FOutDebugStrA
#define FFOutDebugString            FOutDebugStringA
#define FFSaveTextToFile            FSaveTextToFileA
#define FFGetHash                   FGetHashA
#define FFGetHash64                 FGetHash64A
#define FFGetDateStr                FGetDateStrA
#define FFGetDateChar               FGetDateCharA
#define FFGetTimeStr                FGetTimeStrA
#define FFGetTimeChar               FGetTimeCharA
#define FFFileOpenDialog            FFileOpenDialogA
#define FFFileOpenDialogMult        FFileOpenDialogMultA
#define FFBrowserDirDialog          FBrowserDirDialogA
#define FFGetDirFiles               FGetDirFilesA
#define FFGetDirDirs                FGetDirDirsA
#define FFIsSupportPicture          FIsSupportPictureA
#define FFGetSupportPictureFilter   FGetSupportPictureFilterA
#define FFGetSupportPictureExt      FGetSupportPictureExtA
#define FFImageFormatExname         FImageFormatExnameA
#define FFFileRead                  FFileReadA
#define FFOpen                      FOpenA
#define FFIsExist                   FIsExistA
#define FFIsDirectory               FIsDirectoryA
#define FFMakeDirectory             FMakeDirectoryA
#define FFDelDirectory              FDelDirectoryA
#define FFDelFile                   FDelFileA
#define FFReName                    FReNameA
#define FFFileSize                  FFileSizeA
#define FFFileDir                   FFileDirA
#define FFFileName                  FFileNameA
#define FFConvertToSafePath         FConvertToSafePathA
#define FFNormalizeFilepath         FNormalizeFilepathA
#define FFFileNamePosition          FFileNamePositionA
#define FFFileExtPosition           FFileExtPositionA
#define FFFileExtInspect            FFileExtInspectA
#define FFModifyExname              FModifyExnameA
#define FFFileDifferent             FFileDifferentA
#define FFFileType                  FFileTypeA
#define FFTextFileOpen              FTextFileOpenA
#define FFTextFileWrite             FTextFileWriteA
#define FFDllOpen                   FDllOpenA
#define FFDllGet                    FDllGetA
#define FFAtoi                      FAtoiA
#define FFAtof                      FAtofA
#define FFAtod                      FAtodA
#define FFStrcmp                    FStrcmpA
#define FFStrncmp                   FStrncmpA
#define FFStricmp                   FStricmpA
#define FFStrnicmp                  FStrnicmpA
#define FFStrlen                    FStrlenA
#define FFStrnlen                   FStrnlenA
#define FFStrToUpper                FStrToUpperA
#define FFStrToLower                FStrToLowerA
#define FFConvertChar               FConvertCharA
#define FFStrcpy_s                  FStrcpyA_s
#define FFStrcpy                    FStrcpyA
#define FFStrcat_s                  FStrcatA_s
#define FFStrcat                    FStrcatA
#define FFStrchr                    FStrchrA
#define FFMemchr                    FMemchrA
#define FFStrName_cplusplus         FStrName_cplusplusA
#define FFStrName_check             FStrName_checkA
#define FFStrName_add               FStrName_addA
#define FFStrClip                   FStrClipA
#define FFTCHARToUTF8               FANSIToUTF8
#define FFUTF8ToTCHAR               FUTF8ToANSI
#define FFComboString               FComboStringA
#define FFComboStringToType         FComboStringToTypeA
#define FFComboStringToStr          FComboStringToStrA
#define FFGUIDToString              FGUIDToStringA
#define FFGetSysErrorString         FGetSysErrorStringA
#define FFShellExecute              FShellExecuteA
#define FFAboutTool                 FAboutToolA
#define FFPrintErrorMessage         FPrintErrorMessageA
#define FFGenVerifyPicture          FGenVerifyPictureA
#define FFStrFiltrateInit           FStrFiltrateInitA
#define FFStrFiltrate               FStrFiltrateA
#endif


//----------------------------------------------------------------
//
//----------------------------------------------------------------
#include "Core/FBsc_Misc_math_inl.h"
#include "Core/FBsc_Misc_mem_inl.h"
#include "Core/FBsc_Misc_string_inl.h"
